﻿using IM.Easy.Core.Audit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace IM.Easy.Core.Utils
{
    public static class AuditFieldUtils
    {
        // 定义审计接口及其对应的属性
        private static readonly Dictionary<Type, HashSet<string>> AuditInterfaces = new()
            {
                { typeof(ICreatedAt), new HashSet<string> { nameof(ICreatedAt.CreatedAt) } },
                { typeof(IUpdatedAt), new HashSet<string> { nameof(IUpdatedAt.UpdatedAt) } },
                { typeof(ICreatedBy), new HashSet<string> { nameof(ICreatedBy.CreatedBy) } },
                { typeof(IUpdatedBy), new HashSet<string> { nameof(IUpdatedBy.UpdatedBy) } },
                { typeof(IDeletedAt), new HashSet<string> { nameof(IDeletedAt.DeletedAt) } },
                { typeof(IDeletedBy), new HashSet<string> { nameof(IDeletedBy.DeletedBy) } },
                { typeof(IAuditable), new HashSet<string>
                    {
                        nameof(IAuditable.CreatedAt),
                        nameof(IAuditable.UpdatedAt),
                        nameof(IAuditable.CreatedBy),
                        nameof(IAuditable.UpdatedBy),
                        nameof(IAuditable.DeletedAt),
                        nameof(IAuditable.DeletedBy),
                    }
                }
            };

        /// <summary>
        /// 判断给定属性是否为审计字段
        /// </summary>
        /// <param name="property">要检查的属性</param>
        /// <param name="entityType">实体类型</param>
        /// <returns>如果是审计字段返回true，否则返回false</returns>
        public static bool IsAuditProperty(PropertyInfo property, Type entityType)
        {
            // 检查实体实现的所有接口
            foreach (var interfaceType in entityType.GetInterfaces())
            {
                // 检查接口是否在审计接口字典中
                if (AuditInterfaces.TryGetValue(interfaceType, out var auditProperties))
                {
                    // 检查属性名是否在审计属性集合中
                    if (auditProperties.Contains(property.Name))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        /// <summary>
        /// 获取实体中的所有审计字段
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <returns>审计字段列表</returns>
        public static List<PropertyInfo> GetAuditProperties(Type entityType)
        {
            return entityType.GetProperties()
                .Where(property => IsAuditProperty(property, entityType))
                .ToList();
        }

        /// <summary>
        /// 判断实体是否包含任何审计字段
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <returns>如果包含审计字段返回true，否则返回false</returns>
        public static bool HasAuditProperties(Type entityType)
        {
            return entityType.GetInterfaces()
                .Any(interfaceType => AuditInterfaces.ContainsKey(interfaceType));
        }

        /// <summary>
        /// 获取实体实现的审计接口
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <returns>审计接口列表</returns>
        public static List<Type> GetAuditInterfaces(Type entityType)
        {
            return entityType.GetInterfaces()
                .Where(interfaceType => AuditInterfaces.ContainsKey(interfaceType))
                .ToList();
        }


        /// <summary>
        /// 判断字段名是否为审计字段（不区分实体类型，仅根据所有已知审计字段名判断）
        /// </summary>
        /// <param name="fieldName">字段名</param>
        /// <returns>是审计字段返回true，否则返回false</returns>
        public static bool IsAuditFieldName(string fieldName)
        {
            if (string.IsNullOrWhiteSpace(fieldName))
                return false;

            // 合并所有审计字段名
            var allAuditFields = AuditInterfaces.Values.SelectMany(x => x).Distinct(StringComparer.OrdinalIgnoreCase);
            return allAuditFields.Contains(fieldName, StringComparer.OrdinalIgnoreCase);
        }

    }
}
